/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : game_page.c
  * @brief          : select game
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include <stdlib.h>
#include "main.h"
#include "fatfs.h"
#include "lcd.h"
#include "mp3play.h"

#include "game_page.h"

#define OK_KEY_VALUE HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8)

const unsigned char xx2[32] = {0,0,0,0,0,0,0,0,
															2,3,4,5,6,7,8,9,
															12,14,16,18,20,22,24,26,
															30,32,34,36,36,36,36,36};

const unsigned char Cactus_12_24[36] ={0xC0,0xC0,0x00,0x00,0xFE,0xFF,0xFF,0xFE,0x00,0xE0,0xE0,0xC0,0x1F,0x3F,0x60,0x60,
																			0xFF,0xFF,0xFF,0xFF,0x60,0x7F,0x3F,0x1F,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
																			0x00,0x00,0x00,0x00};

const unsigned char Cactus_8_16[2][8] = {0xF0,0xE0,0x00,0xFF,0xFF,0x80,0xFC,0x78,0x13,0x17,0x16,0xFF,0xFF,0x11,0x10,0x10};

	
const unsigned char Dino[2][16] = {0x40,0xC0,0x80,0x00,0x00,0x80,0x80,0xC0,0xFE,0xFF,0xFD,0xBF,0xAF,0x2F,0x0E,0x0C,
																	0x00,0x03,0x07,0x0F,0x1F,0xFF,0x9F,0x1F,0xFF,0x8F,0x07,0x00,0x01,0x00,0x00,0x00};

volatile unsigned long score = 0;																
volatile unsigned char dino_y = 0, speed = 20;														
volatile short xr[4] = {100,150,200,250};

void Dino_Init(void)
{
	LCD_Clean(0x00);
}
																	
void OLED_Display_Dino(char y)
{
	char y_line=0,y_mode =0,i,j;
	
	y_line = 6 - y/8;
	y_mode = y%8;
	
	for(i = 1; i < 6; i++)
	{
		LCD_Set_Pos(0, i);
		for(j=0; j<16; j++)
		{
			LCD_Write_Data(0);
		}
	}
	
	if(y_mode > 0) 
	{
		y_line--;
		
		LCD_Set_Pos(0, y_line);
		for(i=0; i<16; i++)
		{
			LCD_Write_Data((Dino[0][i]  << (8-y_mode)));
		}
		
		LCD_Set_Pos(0, y_line+1);
		for(i=0; i<16; i++)
		{
			LCD_Write_Data((Dino[0][i]  >> (y_mode)) | (Dino[1][i]  << (8-y_mode)));
		}
		
		LCD_Set_Pos(0, y_line+2);
		for(i=0; i<16; i++)
		{
			LCD_Write_Data((Dino[1][i]  >> y_mode));
		}
	}
	else
	{
		LCD_Set_Pos(0, y_line);
		for (i = 0; i < 16; i++)
		{
			LCD_Write_Data(Dino[0][i]);
		}
		
		LCD_Set_Pos(0, y_line+1);
		
		for (i = 0; i < 16; i++)
		{
			LCD_Write_Data(Dino[1][i]);
		}
	}
}


void LCD_Display_Cactus(short x)
{
	char start=0,end=8,i;
	
	if(x < 0)
	{		
		start = 0-x;
		x=0;
	}
	if(x > 120) end = 128 - x;
	
	LCD_Write_Cmd(0x10+((x&0x70)>>4));
	LCD_Write_Cmd(x&0x0F);
	LCD_Write_Cmd(0xB0+6);
	
	for(i=start; i<end; i++)
	{
		LCD_Write_Data(Cactus_8_16[0][i]);
	}
	
	LCD_Write_Cmd(0x10+((x&0x70)>>4));
	LCD_Write_Cmd(x&0x0F);
	LCD_Write_Cmd(0xB0+7);
	for(i=start; i<end; i++)
	{
		LCD_Write_Data(Cactus_8_16[1][i]);
	}
}

void LCD_Draw_Line(unsigned char start, unsigned char len)
{
		unsigned char tmp;
	
		if(start >127) return;
	
		if((start + len) > 128)
		{
			tmp = 128 - start;
		}
		else
		{
			tmp=len;
		}

    LCD_Write_Cmd(0x10+((start&0x70)>>4));
		LCD_Write_Cmd(start&0x0F);
		LCD_Write_Cmd(0xB0+6);
		len = tmp;
		while(len--)LCD_Write_Data(0x00);
	
		len = tmp;
		LCD_Write_Cmd(0x10+((start&0x70)>>4));
		LCD_Write_Cmd(start&0x0F);
		LCD_Write_Cmd(0xB0+7);
		while(len--)LCD_Write_Data(0x10);
}

static void dino_reset(void)
{
	score = 0;																
	dino_y = 0;
	speed = 20;	
	xr[0] = 100;
	xr[1] = 150;
	xr[2] = 200;
	xr[3] = 250;
}

static void game_over(void)
{
	LCD_Disp_Str(35,3, "GAME OVER!", 0);
	HAL_Delay(100);
	g_key_value = 0;
	while(1)
	{
		if(g_key_value == 1) 
		{
			LCD_Clean(0x00);
			dino_reset();
			break;
		}
		HAL_Delay(100);
	}
	printf("Game Restaert\r\n");
}

static void LCD_Refresh(void)
{
		short i = 0;	
		unsigned char ss[8] = { 0 }, c_t, d_t, l_t;

		LCD_Draw_Line(0, xr[0]);
		for(i = 0; i < 3; i++)
		{
			if(i == 1) OLED_Display_Dino(dino_y);
			
			if(xr[i] < 126) 
			{
				LCD_Display_Cactus(xr[i]);
				LCD_Draw_Line(xr[i] + 8, xr[i+1] - xr[i]);
			}
		}
		
		if((xr[0] < 16) && ( dino_y < 16))
		{
			if(xr[0] > 0)
			{
				c_t = 0;
				d_t = xr[0];
				l_t = 16 - xr[0];
			}
			else
			{
				c_t = 0 - xr[0];
				d_t = 0;
				l_t = 8 + xr[0];
			}
			
			while(l_t--)
			{
				if(dino_y > 8)
				{
					if(Cactus_8_16[0][c_t] & (Dino[1][d_t] >> (dino_y - 8))) 
					{
						game_over();
						break;
					}
				}
				else
				{
					if(Cactus_8_16[0][c_t] & ((Dino[0][d_t]  >> (dino_y)) | (Dino[1][d_t]  << (8-dino_y)) ))
					{
						game_over();
						break;
					}
				}
				c_t++; d_t++;
			}
		}
		
		ss[5] = 0;
		ss[4] = (score)%10+48;;
		ss[3] = (score/10)%10+48;
		ss[2] = (score/100)%10+48;
		ss[1] = (score/1000)%10+48;
		ss[0] = (score/10000)%10+48;
		LCD_Disp_Number(0,0,ss);
		
		if(score>8000) speed = 9;
		else if(score>7000) speed = 10;
		else if(score>6000) speed = 11;
		else if(score>5000) speed = 12;
		else if(score>4000) speed = 13;
		else if(score>3000) speed = 14;
		else if(score>2000) speed = 16;
		else if(score>1000) speed = 18;
}

void game_dino_loop(void)
{
	volatile static char jump = 0; //
	volatile static uint32_t LCD_Refresh_Tick = 0;
	volatile static uint32_t Dino_Move_Tick = 0;
	volatile static uint32_t Dino_Jump_Tick = 0;
	
	if(g_key_value == 2)
	{
		g_key_value = 0;
		while(1)
		{
			if(g_key_value == 2) // return
			{
				g_main_while_loop = game_page_loop;
				dino_reset();
				g_key_value = 99;
				return;
				
			}
			if(g_key_value == 1)
			{
				g_key_value = 0;
				break;
			}
			HAL_Delay(100);
		}
	}
	
	if((OK_KEY_VALUE == 1) && (jump == 1)) //
	{
			if((HAL_GetTick() - Dino_Jump_Tick) > xx2[dino_y])
			{
				Dino_Jump_Tick = HAL_GetTick();
				dino_y++;
				if(dino_y == 30) jump = 0; //
			}
	}
	else
	{
		if((HAL_GetTick() - Dino_Jump_Tick) > xx2[dino_y])
		{
			Dino_Jump_Tick = HAL_GetTick();
			if(dino_y)dino_y--;
			if((dino_y == 0) && (OK_KEY_VALUE != 1)) jump = 1;
		}
	}

	if((HAL_GetTick() - Dino_Move_Tick) > speed) //
	{
		Dino_Move_Tick = HAL_GetTick();
		xr[0]--;
		xr[1]--;
		xr[2]--;
		xr[3]--;
		
		if(xr[0] < -5)
		{
			xr[0] = xr[1];
			xr[1] = xr[2];
			xr[2] = xr[3];
			
			xr[3] = xr[3] +50 + rand()%50;
		}
		score++; 
	}
	
	if (HAL_GetTick() - LCD_Refresh_Tick > 100)
	{
		LCD_Refresh_Tick = HAL_GetTick();
		LCD_Refresh();
	}
}
